import os
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, 
                             QFileDialog, QComboBox, QSpinBox, QLineEdit, QGroupBox,
                             QProgressBar, QSlider, QMessageBox)
from PyQt5.QtCore import Qt
from depth_generator import DepthGenerator
from ffmpeg_liber import FFmpegProcessor
from stereo_generator import StereoGenerator
from cleanup_thread import CleanupThread

def create_process_page(main_window):
    """创建视频处理页面"""
    process_widget = QWidget()
    process_widget.setObjectName("tab_content")  # 添加对象名，便于样式应用
    process_layout = QVBoxLayout(process_widget)
    process_layout.setSpacing(15)  # 增加间距
    process_layout.setContentsMargins(20, 20, 20, 20)  # 增加边距
    
    # 视频输入设置
    video_group = QGroupBox("视频输入")
    video_layout = QVBoxLayout(video_group)
    video_layout.setSpacing(8)
    
    # 输入视频行
    video_path_layout = QHBoxLayout()
    video_path_label = QLabel("输入视频:")
    video_path_label.setMinimumWidth(80)
    video_path_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
    main_window.video_path_edit = QLineEdit()
    main_window.video_path_edit.setReadOnly(True)
    video_path_btn = QPushButton("浏览...")
    video_path_btn.setFixedWidth(80)
    video_path_btn.clicked.connect(lambda: select_input_video(main_window))
    
    video_path_layout.addWidget(video_path_label)
    video_path_layout.addWidget(main_window.video_path_edit)
    video_path_layout.addWidget(video_path_btn)
    
    # 帧率设置行
    fps_layout = QHBoxLayout()
    fps_label = QLabel("帧率:")
    fps_label.setMinimumWidth(80)
    fps_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
    main_window.fps_edit = QSpinBox()
    main_window.fps_edit.setRange(1, 120)
    main_window.fps_edit.setValue(30)
    
    fps_layout.addWidget(fps_label)
    fps_layout.addWidget(main_window.fps_edit)
    fps_layout.addStretch()
    
    # 模型选择行
    model_layout = QHBoxLayout()
    model_label = QLabel("深度模型:")
    model_label.setMinimumWidth(80)
    model_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
    main_window.model_combo = QComboBox()
    
    # 确保depth_thread已正确初始化
    if not hasattr(main_window, 'depth_thread') or main_window.depth_thread is None:
        main_window.depth_thread = DepthGenerator(main_window.midas_accel)
        main_window.depth_thread.log_message.connect(main_window.append_log)
    
    # 连接available_models信号
    main_window.depth_thread.available_models.connect(lambda models: update_model_list(main_window, models))
    
    # 扫描可用模型
    main_window.depth_thread.scan_available_models()
    
    model_layout.addWidget(model_label)
    model_layout.addWidget(main_window.model_combo)
    model_layout.addStretch()
    
    # 扫描models目录下的模型
    models_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "models")
    if not os.path.exists(models_dir):
        os.makedirs(models_dir)
    
    # 添加到视频输入组
    video_layout.addLayout(video_path_layout)
    video_layout.addLayout(fps_layout)
    video_layout.addLayout(model_layout)
    
    # 添加视差强度控制
    shift_strength_group = QGroupBox("视差强度设置")
    shift_strength_layout = QVBoxLayout(shift_strength_group)
    
    # 添加设备类型选择
    device_layout = QHBoxLayout()
    device_label = QLabel("设备类型:")
    main_window.device_combo = QComboBox()
    main_window.device_combo.addItem("手机/平板 (0.02-0.05)")
    main_window.device_combo.addItem("显示器/电视 (0.05-0.08)")
    main_window.device_combo.addItem("影院/VR头显 (0.08-0.12)")
    main_window.device_combo.currentIndexChanged.connect(lambda: update_shift_strength_range(main_window))
    
    device_layout.addWidget(device_label)
    device_layout.addWidget(main_window.device_combo)
    device_layout.addStretch()
    
    # 视差强度滑动条
    main_window.shift_strength_slider = QSlider(Qt.Horizontal)
    main_window.shift_strength_slider.setMinimum(1)
    main_window.shift_strength_slider.setMaximum(100)
    main_window.shift_strength_slider.setValue(50)  # 默认值50%
    main_window.shift_strength_slider.setTickPosition(QSlider.TicksBelow)
    main_window.shift_strength_slider.setTickInterval(10)
    
    main_window.shift_strength_label = QLabel("视差强度: 0.05")
    main_window.shift_strength_slider.valueChanged.connect(lambda value: update_shift_strength_label(main_window, value))
    
    shift_strength_layout.addLayout(device_layout)
    shift_strength_layout.addWidget(main_window.shift_strength_label)
    shift_strength_layout.addWidget(main_window.shift_strength_slider)
    
    # 进度条区域
    progress_layout = QHBoxLayout()
    progress_label = QLabel("处理进度:")
    main_window.process_progress_bar = QProgressBar()
    main_window.process_progress_bar.setRange(0, 100)
    main_window.process_progress_bar.setValue(0)
    
    progress_layout.addWidget(progress_label)
    progress_layout.addWidget(main_window.process_progress_bar)
    
    # 按钮区域
    buttons_layout = QHBoxLayout()
    main_window.process_start_btn = QPushButton("生成")
    main_window.process_cancel_btn = QPushButton("取消")
    
    main_window.process_start_btn.clicked.connect(lambda: start_processing(main_window))
    main_window.process_cancel_btn.clicked.connect(lambda: cancel_processing(main_window))
    
    buttons_layout.addStretch()
    buttons_layout.addWidget(main_window.process_start_btn)
    buttons_layout.addWidget(main_window.process_cancel_btn)
    
    # 添加到处理页面
    process_layout.addWidget(video_group)
    process_layout.addWidget(shift_strength_group)
    process_layout.addSpacing(5)
    process_layout.addLayout(progress_layout)
    process_layout.addSpacing(5)
    process_layout.addLayout(buttons_layout)
    process_layout.addStretch()
    
    # 添加到标签页
    main_window.content_stack.addTab(process_widget, "视频处理")
    
    return process_widget

def select_input_video(main_window):
    """选择输入视频"""
    file_dialog = QFileDialog(main_window)
    file_dialog.setWindowTitle("选择输入视频")
    file_dialog.setNameFilter("视频文件 (*.mp4 *.avi *.mkv *.mov *.wmv)")
    file_dialog.setFileMode(QFileDialog.ExistingFile)
    
    if file_dialog.exec_():
        selected_files = file_dialog.selectedFiles()
        if selected_files:
            video_path = selected_files[0]
            main_window.input_video = video_path
            main_window.video_path_edit.setText(video_path)
            main_window.append_log(f"已选择输入视频: {video_path}")

def update_model_list(main_window, model_list):
    """更新模型下拉列表"""
    main_window.model_combo.clear()
    for model in model_list:
        main_window.model_combo.addItem(model)
    
    # 如果有模型，选择第一个
    if model_list:
        main_window.model = model_list[0]

def update_shift_strength_range(main_window):
    """根据设备类型更新视差强度范围"""
    device_index = main_window.device_combo.currentIndex()
    
    # 设置不同设备类型的视差强度范围
    if device_index == 0:  # 手机/平板
        main_window.min_strength = 0.02
        main_window.max_strength = 0.05
    elif device_index == 1:  # 显示器/电视
        main_window.min_strength = 0.05
        main_window.max_strength = 0.08
    elif device_index == 2:  # 影院/VR头显
        main_window.min_strength = 0.08
        main_window.max_strength = 0.12
    
    # 更新标签
    update_shift_strength_label(main_window, main_window.shift_strength_slider.value())

def update_shift_strength_label(main_window, value):
    """更新视差强度标签"""
    # 确保min_strength和max_strength已定义
    if not hasattr(main_window, 'min_strength'):
        main_window.min_strength = 0.02
        main_window.max_strength = 0.05
    
    # 将滑动条值(1-100)映射到实际视差强度范围
    strength = main_window.min_strength + (value / 100.0) * (main_window.max_strength - main_window.min_strength)
    strength = round(strength, 3)  # 保留3位小数
    
    main_window.shift_strength_label.setText(f"视差强度: {strength}")

def start_processing(main_window):
    """开始处理视频"""
    # 检查是否已设置FFmpeg路径
    if not main_window.ffmpeg_path or not os.path.exists(main_window.ffmpeg_path):
        QMessageBox.warning(main_window, "警告", "请先设置FFmpeg路径")
        return
    
    # 检查是否已选择输入视频
    if not main_window.input_video or not os.path.exists(main_window.input_video):
        QMessageBox.warning(main_window, "警告", "请先选择输入视频")
        return
    
    # 清除日志控件的历史显示
    main_window.log_text.clear()
    main_window.append_log("开始新的视频处理任务...")
    
    # 获取帧率和模型
    main_window.fps = main_window.fps_edit.value()
    main_window.model = main_window.model_combo.currentText()
    
    # 获取视差强度
    slider_value = main_window.shift_strength_slider.value()
    shift_strength = main_window.min_strength + (slider_value / 100.0) * (main_window.max_strength - main_window.min_strength)
    shift_strength = round(shift_strength, 3)  # 保留3位小数
    
    # 获取硬件加速选项
    main_window.ffmpeg_accel = main_window.ffmpeg_accel_combo.currentText()
    main_window.midas_accel = main_window.midas_accel_combo.currentText()
    main_window.stereo_accel = main_window.stereo_accel_combo.currentText()
    
    # 禁用按钮并重置进度条
    main_window.process_start_btn.setEnabled(False)
    main_window.process_cancel_btn.setEnabled(True)
    main_window.process_progress_bar.setValue(0)
    
    # 创建输出目录
    output_dir = os.path.dirname(main_window.input_video)
    frames_dir = os.path.join(output_dir, "frames")
    depth_dir = os.path.join(output_dir, "depth")
    left_eye_dir = os.path.join(output_dir, "left_eye")
    right_eye_dir = os.path.join(output_dir, "right_eye")
    
    # 使用线程清除旧文件
    main_window.append_log("清除旧文件...")
    main_window.cleanup_thread = CleanupThread()
    main_window.cleanup_thread.set_directories([frames_dir, depth_dir, left_eye_dir, right_eye_dir])
    
    # 连接信号
    main_window.cleanup_thread.log_message.connect(main_window.append_log)
    main_window.cleanup_thread.cleanup_completed.connect(
        lambda success, msg: on_cleanup_completed(main_window, success, msg, frames_dir, depth_dir, left_eye_dir, right_eye_dir)
    )
    
    # 启动清理线程
    main_window.cleanup_thread.start()

def on_cleanup_completed(main_window, success, message, frames_dir, depth_dir, left_eye_dir, right_eye_dir):
    """清理完成回调"""
    if not success:
        main_window.append_log(f"清理失败: {message}")
        main_window.process_start_btn.setEnabled(True)
        main_window.process_cancel_btn.setEnabled(False)
        return
    
    # 第一步：使用FFmpeg提取帧
    main_window.append_log("===== 步骤1：提取视频帧 =====")
    # 使用main_window.ffmpeg_accel作为硬件加速选项
    main_window.ffmpeg_thread = FFmpegProcessor(main_window.ffmpeg_path, main_window.ffmpeg_accel)
    main_window.ffmpeg_thread.input_video = main_window.input_video
    main_window.ffmpeg_thread.frames_dir = frames_dir  # 设置输出帧目录
    main_window.ffmpeg_thread.fps = main_window.fps
    main_window.ffmpeg_thread.operation_type = "extract_frames"
    
    main_window.ffmpeg_thread.progress_updated.connect(lambda p: update_progress(main_window, p, "提取帧"))
    main_window.ffmpeg_thread.log_message.connect(main_window.append_log)
    main_window.ffmpeg_thread.process_completed.connect(
        lambda success, msg: on_frames_extracted(main_window, success, msg, frames_dir, depth_dir, left_eye_dir, right_eye_dir)
    )
    
    main_window.ffmpeg_thread.start()

def on_frames_extracted(main_window, success, message, frames_dir, depth_dir, left_eye_dir, right_eye_dir):
    """帧提取完成回调"""
    if not success:
        main_window.append_log(f"帧提取失败: {message}")
        main_window.process_start_btn.setEnabled(True)
        main_window.process_cancel_btn.setEnabled(False)
        
        # 添加失败提示对话框
        QMessageBox.critical(main_window, "处理失败", f"帧提取失败: {message}")
        return
    
    # 第二步：生成深度图
    main_window.append_log("\n===== 步骤2：生成深度图 =====")
    main_window.depth_thread = DepthGenerator(main_window.midas_accel)
    main_window.depth_thread.frames_dir = frames_dir
    main_window.depth_thread.depth_dir = depth_dir
    main_window.depth_thread.model_type = main_window.model
    
    main_window.depth_thread.progress_updated.connect(lambda p: update_progress(main_window, p, "生成深度图"))
    main_window.depth_thread.log_message.connect(main_window.append_log)
    main_window.depth_thread.process_completed.connect(
        lambda success, msg: on_depth_generated(main_window, success, msg, frames_dir, depth_dir, left_eye_dir, right_eye_dir)
    )
    
    main_window.depth_thread.start()

def on_depth_generated(main_window, success, message, frames_dir, depth_dir, left_eye_dir, right_eye_dir):
    """深度图生成完成回调"""
    if not success:
        main_window.append_log(f"深度图生成失败: {message}")
        main_window.process_start_btn.setEnabled(True)
        main_window.process_cancel_btn.setEnabled(False)
        
        # 添加失败提示对话框
        QMessageBox.critical(main_window, "处理失败", f"深度图生成失败: {message}")
        return
    
    # 第三步：生成左右眼视图
    main_window.append_log("\n===== 步骤3：生成左右眼视图 =====")
    main_window.stereo_thread = StereoGenerator()
    main_window.stereo_thread.frames_dir = frames_dir
    main_window.stereo_thread.depth_dir = depth_dir
    main_window.stereo_thread.left_eye_dir = left_eye_dir
    main_window.stereo_thread.right_eye_dir = right_eye_dir
    
    # 设置视差强度 - 添加错误处理
    try:
        shift_strength = main_window.shift_strength_slider.value() / 100.0
        main_window.append_log(f"视差强度设置为: {shift_strength:.2f}")
    except AttributeError:
        # 如果滑动条不存在，使用默认值
        main_window.append_log("未找到视差强度滑动条，使用默认值0.5")
        shift_strength = 0.5
    
    main_window.stereo_thread.set_shift_strength(shift_strength)
    
    # 设置硬件加速选项
    main_window.stereo_thread.set_hardware_accel(main_window.stereo_accel)
    
    # 设置并行处理选项
    use_parallel = main_window.parallel_check.isChecked()
    num_workers = main_window.threads_spin.value()
    main_window.stereo_thread.set_parallel_processing(use_parallel, num_workers)
    
    main_window.stereo_thread.progress_updated.connect(lambda p: update_progress(main_window, p, "生成左右眼视图"))
    main_window.stereo_thread.log_message.connect(main_window.append_log)
    
    # 修复这里的lambda函数，确保参数匹配
    main_window.stereo_thread.process_completed.connect(
        lambda success, msg: on_stereo_generated(main_window, success, msg, frames_dir, depth_dir)
    )
    
    main_window.stereo_thread.start()

def on_stereo_generated(main_window, success, message, frames_dir, depth_dir):
    """左右眼视图生成完成回调"""
    if not success:
        main_window.append_log(f"左右眼视图生成失败: {message}")
        main_window.process_start_btn.setEnabled(True)
        main_window.process_cancel_btn.setEnabled(False)
        return
    
    # 获取左右眼目录
    left_eye_dir = os.path.join(os.path.dirname(frames_dir), "left_eye")
    right_eye_dir = os.path.join(os.path.dirname(frames_dir), "right_eye")
    
    # 第四步：合成左右眼视频
    main_window.append_log("\n===== 步骤4：合成左右眼视频 =====")
    
    # 创建左眼视频路径
    left_video_path = os.path.join(os.path.dirname(left_eye_dir), "left_eye.mp4")
    
    # 使用FFmpeg线程来创建视频，避免阻塞GUI
    # 使用main_window.ffmpeg_accel作为硬件加速选项
    main_window.ffmpeg_thread = FFmpegProcessor(main_window.ffmpeg_path, main_window.ffmpeg_accel)
    main_window.ffmpeg_thread.frames_dir = left_eye_dir
    main_window.ffmpeg_thread.output_video = left_video_path
    main_window.ffmpeg_thread.operation_type = "create_video"
    main_window.ffmpeg_thread.fps = main_window.fps
    
    main_window.append_log(f"开始创建左眼视频...")
    
    # 连接信号
    main_window.ffmpeg_thread.progress_updated.connect(lambda p: update_progress(main_window, p, "创建左眼视频"))
    main_window.ffmpeg_thread.log_message.connect(main_window.append_log)
    main_window.ffmpeg_thread.process_completed.connect(lambda success, msg: on_left_video_created(main_window, success, msg, right_eye_dir))
    
    # 启动线程
    main_window.ffmpeg_thread.start()

def on_left_video_created(main_window, success, message, right_eye_dir):
    """左眼视频创建完成回调"""
    if not success:
        main_window.append_log(f"左眼视频创建失败: {message}")
        main_window.process_start_btn.setEnabled(True)
        main_window.process_cancel_btn.setEnabled(False)
        return
    
    # 创建右眼视频路径
    right_video_path = os.path.join(os.path.dirname(right_eye_dir), "right_eye.mp4")
    
    # 使用FFmpeg线程来创建视频
    # 使用main_window.ffmpeg_accel作为硬件加速选项
    main_window.ffmpeg_thread = FFmpegProcessor(main_window.ffmpeg_path, main_window.ffmpeg_accel)
    main_window.ffmpeg_thread.frames_dir = right_eye_dir
    main_window.ffmpeg_thread.output_video = right_video_path
    main_window.ffmpeg_thread.operation_type = "create_video"
    main_window.ffmpeg_thread.fps = main_window.fps
    
    main_window.append_log(f"开始创建右眼视频...")
    
    # 连接信号
    main_window.ffmpeg_thread.progress_updated.connect(lambda p: update_progress(main_window, p, "创建右眼视频"))
    main_window.ffmpeg_thread.log_message.connect(main_window.append_log)
    main_window.ffmpeg_thread.process_completed.connect(lambda success, msg: on_right_video_created(main_window, success, msg, right_video_path))
    
    # 启动线程
    main_window.ffmpeg_thread.start()

def on_right_video_created(main_window, success, message, right_video_path):
    """右眼视频创建完成回调"""
    if not success:
        main_window.append_log(f"右眼视频创建失败: {message}")
        main_window.process_start_btn.setEnabled(True)
        main_window.process_cancel_btn.setEnabled(False)
        
        # 添加失败提示对话框
        QMessageBox.critical(main_window, "处理失败", f"右眼视频创建失败: {message}")
        return
    
    # 获取左眼视频路径
    left_video_path = os.path.join(os.path.dirname(right_video_path), "left_eye.mp4")
    
    main_window.append_log("处理完成！")
    main_window.append_log(f"左眼视频: {left_video_path}")
    main_window.append_log(f"右眼视频: {right_video_path}")
    
    # 处理完成，启用按钮
    main_window.process_start_btn.setEnabled(True)
    main_window.process_cancel_btn.setEnabled(False)
    
    # 更新进度条为100%
    update_progress(main_window, 100, "视频处理")
    
    # 添加成功提示对话框
    QMessageBox.information(main_window, "处理完成", 
                           f"裸眼3D视频处理完成！\n\n左眼视频: {os.path.basename(left_video_path)}\n右眼视频: {os.path.basename(right_video_path)}")

def cancel_processing(main_window):
    """取消视频处理"""
    if main_window.cleanup_thread and hasattr(main_window.cleanup_thread, 'is_running') and main_window.cleanup_thread.is_running:
        main_window.cleanup_thread.stop()
        main_window.append_log("取消清理操作")
    
    if main_window.ffmpeg_thread and hasattr(main_window.ffmpeg_thread, 'is_running') and main_window.ffmpeg_thread.is_running:
        main_window.ffmpeg_thread.stop()
        main_window.append_log("取消帧提取")
    
    if main_window.depth_thread and hasattr(main_window.depth_thread, 'is_running') and main_window.depth_thread.is_running:
        main_window.depth_thread.stop()
        main_window.append_log("取消深度图生成")
    
    if main_window.stereo_thread and hasattr(main_window.stereo_thread, 'is_running') and main_window.stereo_thread.is_running:
        main_window.stereo_thread.stop()
        main_window.append_log("取消左右眼视图生成")
    
    main_window.process_start_btn.setEnabled(True)
    main_window.process_cancel_btn.setEnabled(False)
    main_window.process_progress_bar.setValue(100)

def update_progress(main_window, value, operation_type=""):
    """更新进度条"""
    # 更新进度条和日志
    if operation_type:
        main_window.append_log(f"{operation_type}进度: {value}%")
        
        # 根据操作类型更新对应的进度条
        if "提取帧" in operation_type or "生成深度图" in operation_type or "生成左右眼视图" in operation_type or "创建左眼视频" in operation_type or "创建右眼视频" in operation_type:
            main_window.process_progress_bar.setValue(value)
        elif "合并视频" in operation_type:
            if hasattr(main_window, 'merge_progress_bar'):
                main_window.merge_progress_bar.setValue(value)